use super::Scheduler;
use core::cell::Cell;
use core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
use core::ptr;
use core::time::Duration;
use hicollections::{rbtree, RbTree, RbTreeNode};

#[repr(C)]
pub struct Timer {
    pub(crate) node: RbTreeNode,
    pub(crate) timeout: Cell<Duration>,
    handle: fn(&Timer, &mut Scheduler),
}

pub fn timer_rbtree_new() -> RbTree<Timer> {
    rbtree!(Timer, node)
}

impl PartialOrd for Timer {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl PartialEq for Timer {
    fn eq(&self, other: &Self) -> bool {
        ptr::eq(self, other)
    }
}

impl Eq for Timer {}

impl Ord for Timer {
    fn cmp(&self, other: &Self) -> Ordering {
        match self.timeout.cmp(&other.timeout) {
            Ordering::Equal => (self as *const Self).cmp(&(other as *const Self)),
            ord => ord,
        }
    }
}

impl Timer {
    pub fn new(handle: fn(&Timer, &mut Scheduler)) -> Self {
        Self {
            node: RbTreeNode::new(),
            timeout: Cell::new(Duration::new(0, 0)),
            handle,
        }
    }
    pub fn handle(&self, sched: &mut Scheduler) {
        (self.handle)(self, sched)
    }
}
